Togglz
install dependence
for spring MVC development:
build.gradle
compile ‘org.togglz:togglz-servlet:2.6.1.Final’
compile ‘org.togglz:togglz-spring-web:2.6.1.Final’
runtime ‘org.togglz:togglz-jsp:2.6.1.Final’
compile ‘org.togglz:togglz-console:2.6.1.Final’
for spring boot development:
build.gradle
2.x:
compile(“org.togglz:togglz-spring-boot-starter:2.6.1.Final”)
1.x:
compile(“org.togglz:togglz-legacy-spring-boot-starter:2.6.1.Final”)
note: The starter will not only add the togglz-core
and togglz-spring-core
modules to your project, it will also enable the auto configuration of the Togglz configration.
Configuration
Configuring Togglz requires you to implement two classes.
Feature definition
The first class is the feature enum which declares the features you want to manage with Togglz. This enum is a standard Java enum which implements the Feature
interface.
import org.togglz.core.Feature;
import org.togglz.core.annotation.EnabledByDefault;
import org.togglz.core.annotation.Label;
import org.togglz.core.context.FeatureContext;
public enum MyFeatures implements Feature {
@Label("First Feature")
FEATURE_ONE,
@Label("Second Feature")
FEATURE_TWO;
public boolean isActive() {
return FeatureContext.getFeatureManager().isActive(this);
}
}
Implementing TogglzConfig
The next step is to configure the FeatureManager
which is the central Togglz component that manages the state of your features. To do so, you have to create a class implementing the TogglzConfig
.
import java.io.File;
import org.togglz.core.Feature;
import org.togglz.core.manager.TogglzConfig;
import org.togglz.core.repository.StateRepository;
import org.togglz.core.repository.file.FileBasedStateRepository;
import org.togglz.core.user.FeatureUser;
import org.togglz.core.user.UserProvider;
import org.togglz.servlet.user.ServletUserProvider
@Component
public class MyTogglzConfiguration implements TogglzConfig {
@Override
public Class<? extends Feature> getFeatureClass() {
return MyFeatures.class;
}
@Override
public StateRepository getStateRepository() {
return new FileBasedStateRepository(new File("features.properties"));
}
@Override
public UserProvider getUserProvider() {
return () -> new SimpleFeatureUser("admin", true);
}
}
Note:the relative path is direct to the project path(eg. /twu63team2)
features.properties
FEATURE_TWO=false
FEATURE_ONE=false
Important Note: if you use spring security, it will use csrf protection which cause that you can not use togglz admin console to edit the status of feature.
one way to solve that problem is to disable the csrf.(not recommend)
security-app-context.xml:
<http>
<csrf disabled="true"/>
</http>
another way is to import one more dependence in build.gradle
compile ‘org.togglz:togglz-spring-security:2.6.1.Final’
once you import this dependence, when you edit the toggle state in admin console, It will add a csrf token, and it will work!
Usage
Java
if( MyFeatures.FEATURE_ONE.isActive() ) {
// new stuff here
}
JSP
<%@ taglib uri="http://togglz.org/taglib" prefix="togglz" %>
This is some text that is always shown.
<togglz:feature name="FEATURE_ONE">
This is the text of the TEXT feature.
</togglz:feature>
Test with togglz
if you use junit for test, you need to add test dependence for togglz in build.gradle
testCompile ‘org.togglz:togglz-junit:2.6.1.Final’
TogglzRule
The first important feature of the JUnit integration module is the TogglzRule
. This rule allows to modify the feature state at runtime. This is especially useful if you want to test a special combination of feature states.
public class SomeJunitTest {
@Rule
public TogglzRule togglzRule = TogglzRule.allEnabled(MyFeatures.class);
@Test
public void testToggleFeature() {
// all features are active by default
assertTrue(MyFeatures.FEATURE_ONE.isActive());
// you can easily modify the feature state using the TogglzRule
togglzRule.disable(MyFeatures.FEATURE_ONE);
assertFalse(MyFeatures.FEATURE_ONE.isActive());
}
}
Feature variations
The JUnit integration module also allows to run tests with different combination of feature states. This works very similar to JUnit’s @Parameterized
annotation.
@RunWith(FeatureVariations.class)
public class FeatureVariationsTest {
@Variations
public static VariationSet<MyFeatures> getPermutations() {
return VariationSetBuilder.create(MyFeatures.class)
.enable(MyFeatures.F1)
.vary(MyFeatures.F2)
.vary(MyFeatures.F3);
}
// will be executed 4 times
@Test
public void test() {
assertTrue(MyFeatures.F1.isActive());
assertTrue(MyFeatures.F2.isActive() || !MyFeatures.F2.isActive());
assertTrue(MyFeatures.F3.isActive() || !MyFeatures.F3.isActive());
}
}
- F1=on, F2=off, F3=off
- F1=on, F2=on, F3=off
- F1=on, F2=off, F3=on
- F1=on, F2=on, F3=on